<?php 
namespace app\common\service\queue;
use think\facade\Db;
use app\common\model\Timing as TimingModel;
use helper\URL;
use helper\Time;
use think\cache\driver\Redis;
class Timing
{
    public function subscribe_handle()
    {
        Db::startTrans();
        $Model=TimingModel::where(['status'=>1])->whereTime('next_time','<',time())->lock(true)->find();
        if ($Model) {
            $Model->status=1;
            $Model->last_time=time();
            $Model->next_time=$this->getNextTime($Model);
            $Model->save();
            $redisConfig=config('cache.stores.redis');
            $redis=new Redis($redisConfig);
            $redis->lpush($redisConfig['prefix']."TimingTask-list", json_encode(['type'=>$Model->type,'content'=>$Model->content]));
        }
        Db::commit();
    }
    public function release_handle()
    {
        $redisConfig=config('cache.stores.redis');
        $redis=new Redis($redisConfig);
        $taskData = $redis->lpop($redisConfig['prefix']."TimingTask-list");
        $taskData=json_decode($taskData);
        if($taskData){
            switch ($taskData->type) {
                case 'script':
                    try {
                        $Obj=json_decode($taskData->content);
                        if($Obj&&class_exists($Obj->class)){
                            $task=new $Obj->class;
                            if ($Obj->data)
                                $task->setData($Obj->data);
                            $ret=$task->run();
                        }
                    } catch (\think\Exception $e) {
                    } catch (\think\exception\ErrorException $e) {
                    }
                    break;
                case 'get_url':
                    URL::get($taskData->content);
                    $ret=true;
                    break;
            }
        }
    }
    public function getNextTime($Model)
    {
        $now=time();
        switch ($Model->time_type) {
            //每天
            case 0:
                return strtotime("+1 days",strtotime(date('Y-m-d ').$Model->hour.':'.$Model->minute.':00'));
            //N天
            case 1:
                return $now+Time::daysToSecond($Model->day)+($Model->hour*3600)+($Model->minute*60);
            //每小时
            case 2:
                return strtotime(date('Y-m-d H:',$now).$Model->minute.':00');
            //N小时
            case 3:
                return $now+($Model->hour*3600)+($Model->minute*60);
            //N分钟
            case 4:
                return $now+($Model->minute*60);
            //每星期
            case 5:
                $week=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
                return strtotime(date('Y-m-d ',strtotime("next ".$week[$Model->week],$now)).$Model->hour.':'.$Model->minute.':00');
            //每月
            case 6:
                return strtotime("+1 Month",strtotime(date('Y-m-').$Model->day.' '.$Model->hour.':'.$Model->minute.':00'));
        }
    }
    public function runTask($Model)
    {
        $ret=false;
        if ($Model) {
            $Model->status=1;
            $Model->last_time=time();
            $Model->next_time=$this->getNextTime($Model);
            $Model->save();
            Db::commit();
            switch ($Model->type) {
                case 'script':
                    try {
                        $Obj=json_decode($Model->content);
                        if($Obj&&class_exists($Obj->class)){
                            $task=new $Obj->class;
                            if ($Obj->data)
                                $task->setData($Obj->data);
                            $ret=$task->run();
                        }
                    } catch (\think\Exception $e) {
                        dd($e->getMessage());
                    } catch (\think\exception\ErrorException $e) {
                    }
                    break;
                case 'get_url':
                    URL::get($Model->content);
                    $ret=true;
                    break;
            }
        }else{
            Db::commit();
        }
        return $ret;
    }
}